#include "GameHUD.h"
#include "GraphicsInterface.h"
#include <string>

//Converts std::string to wstring.
std::wstring ToWS(std::string s)
{
    int len;
    int slength = (int)s.length() + 1;
    len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0); 
    wchar_t* buf = new wchar_t[len];
    MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
    std::wstring r(buf);
    delete[] buf;
    return r;
}


GameHUD::GameHUD()
{
	font = 0;
	spriteBatch = 0;
	orbImage = 0;
	medalImage = 0;
	isActive = false;

	// Should start at 0
	numCollectables = 0;
	numMedals = 0;

	// Loop though each segment of health
	for (int i=0; i<NUM_HEALTH_SEGMENTS; i++)
	{
		healthImages[i] = 0;
	}
}

GameHUD::~GameHUD()
{
	// Clean up
	SafeDelete(font);
	SafeDelete(spriteBatch);
	ReleaseCOM(orbImage);
	ReleaseCOM(medalImage);

	// Loop though each segment of health
	for (int i=0; i<NUM_HEALTH_SEGMENTS; i++)
	{
		ReleaseCOM(healthImages[i]);
	}
}

void GameHUD::Initalise(ID3D11Device* device)
{
	// Load fonts. 
	font = new FontSheet();
	spriteBatch = new SpriteBatch();

	// Init sprite batch and font
	HR(font->Initialize(device, L"Times New Roman", 96.0f, FontSheet::FontStyleItalic, true));
	HR(spriteBatch->Initialize(device));

	// Load 2D images for the diffrent health displays, 1 for each health segment
	HR(D3DX11CreateShaderResourceViewFromFile(device, L"HUD/Health_1.png", 0, 0, &healthImages[0],0));
	HR(D3DX11CreateShaderResourceViewFromFile(device, L"HUD/Health_2.png", 0, 0, &healthImages[1],0));
	HR(D3DX11CreateShaderResourceViewFromFile(device, L"HUD/Health_3.png", 0, 0, &healthImages[2],0));
	HR(D3DX11CreateShaderResourceViewFromFile(device, L"HUD/Health_4.png", 0, 0, &healthImages[3],0));
	HR(D3DX11CreateShaderResourceViewFromFile(device, L"HUD/Health_5.png", 0, 0, &healthImages[4],0));
	HR(D3DX11CreateShaderResourceViewFromFile(device, L"HUD/Health_6.png", 0, 0, &healthImages[5],0));
	
	// Load the collectable Images
	HR(D3DX11CreateShaderResourceViewFromFile(device, L"HUD/Orbs_Image.png", 0, 0, &orbImage,0));
	HR(D3DX11CreateShaderResourceViewFromFile(device, L"HUD/Medal_Image.png", 0, 0, &medalImage,0));
}

// HUD should remain on screen for 5 seconds before been set to inactive
void GameHUD::Update(float delta)
{
	// When the HUD is not active and upon keypress begin rendering
	if (!isActive && (GetAsyncKeyState('Q') & 0x8000))
		// HUD is now active
		isActive = true;

	// If the HUD is already active stop rendering the HUD
	else if (isActive && (GetAsyncKeyState('Q') & 0x8000))
		// HUD is toggled off
		isActive = false;
}

void GameHUD::RenderHUD(GraphicsInterface* gi, Player* player)
{
	// ------------------------------------------------------------------------------------
	//									For basic HUD
	// ------------------------------------------------------------------------------------

	// Use this as an ID number to render the correct image
	int healthImageID;

	// Same image will be used for when the player has 0 health and 1 health remaining.
	// As it seems sorta pointless flashing an empty health bar for however long the player
	// remains dead (may even be possible that the player insta respawns).
	if (player->GetHealth() == 0 || player->GetHealth() == 1)
		healthImageID = 0;
	// Use the corresponding health bar image and ammend the number to match the array.
	else
		healthImageID = player->GetHealth() - 1;
	
	// Draw 2D texture depended on health. 
	spriteBatch->BeginBatch(healthImages[healthImageID]);
	spriteBatch->AddSpriteToBatch(gi, 0.02f, 0.02f, 0.1f, 0.1f);
	spriteBatch->EndBatch(gi->GetContext());

	// Draw the orb collectable image
	spriteBatch->BeginBatch(orbImage);
	spriteBatch->AddSpriteToBatch(gi, 0.6f, 0.02f, 0.1f, 0.1f);
	spriteBatch->EndBatch(gi->GetContext());

	//For the collectables, we need to convert ints to a string and then to wstring- we therefore
	//use string stream as its awesome at this!
	std::stringstream ss, ss2;
	ss << numCollectables;
	ss2 << numMedals;

	std::wstring wNumCollecablesStr = ToWS(ss.str());
	std::wstring wNumMedalsStr = ToWS(ss2.str());

	std::wstring orbString = std::wstring(wNumCollecablesStr + L"/15");
	// Add text for the orb collectables: Should be 15 in total
	spriteBatch->DrawStringUnorm(gi, *font, orbString, 0.7f, 0.02f);

	// Draw the medal collectable image
	spriteBatch->BeginBatch(medalImage);
	spriteBatch->AddSpriteToBatch(gi, 0.8f, 0.02f, 0.1f, 0.1f);
	spriteBatch->EndBatch(gi->GetContext());

	std::wstring medalString = std::wstring(wNumMedalsStr + L"/4");
	// Add text for the medal collectables: Should be 4 in total
	spriteBatch->DrawStringUnorm(gi, *font, medalString, 0.9f, 0.02f);

	// ------------------------------------------------------------------------------------
	//									For quest timer
	// ------------------------------------------------------------------------------------
	
	if(player->GetCurrentQuest())
	{
		std::stringstream ss3;
		
		ss3 << player->GetCurrentQuest()->GetTimeLimit();

		std::wstring wQuestTime = ToWS(ss3.str());

		spriteBatch->DrawStringUnorm(gi, *font, wQuestTime, 0.5f, 0.9f);
	}
}

void GameHUD::SetIsActive(bool active)
{
	isActive = active;
}

void GameHUD::SetNumMedals(int medals)
{
	numMedals = medals;
}

void GameHUD::SetNumCollectables(int collectables)
{
	numCollectables = collectables;
}